package contrl

import (
	"core/env"
	"core/minio_client"
	"core/mysql"
	"core/utils"
	"db"
	"fmt"
	"strings"

	"github.com/gin-gonic/gin"
)

type PictureContrl struct{}

const (
	PictureTypeOriginal = 0
	PictureTypeLove     = 1
	PictureTypeConsider = 2
)

type PictureItem struct {
	ID         int64  `json:"id"`
	OriginName string `json:"origin_name"`
	Width      int    `json:"width"`
	Height     int    `json:"height"`
	URL        string `json:"url"`
	MiniURL    string `json:"miniUrl"`
	AuthUID    int64  `json:"auth_uid"`
	AuthName   string `json:"auth_name"`
	Comment    string `json:"comment"`
	Feel       int    `json:"feel"`
	State      string `json:"state"`
}

func genPictureURL(name string) string {
	return fmt.Sprintf("http://%s/image/%s", env.Confs[env.RunModeAdminProd].ServerUrl, name)
}

func genPicMiniHeight(width, height, newWidth int) (newHeight int) {
	return int((float64(newWidth) / float64(width)) * float64(height))
}

type PictureListRes struct {
	Count int64
	List  []PictureItem
}

// 图片列表
func (*PictureContrl) ListOriginal(c *gin.Context) (res interface{}, e Error) {
	page := utils.Max(GetInt(c, "page"), 1)
	rows := utils.Min(GetInt(c, "rows"), 30)

	pictures := make([]db.PicOriginalMysql, 0)
	count, err := mysql.FindList(&pictures, &mysql.Cond{
		Start: (page - 1) * rows,
		Limit: rows,
		Asc:   "id",
	})
	if err != nil {
		return nil, GenError(err)
	}

	list := make([]PictureItem, len(pictures))
	for k, picture := range pictures {
		list[k] = PictureItem{
			ID:         picture.ID,
			OriginName: picture.OriginName,
			Width:      100,
			Height:     genPicMiniHeight(picture.Width, picture.Height, 100),
			URL:        genPictureURL(picture.Name),
			MiniURL:    genPictureURL(env.GetMinPicName(picture.Name)),
			AuthName:   picture.AuthorName,
			AuthUID:    picture.AuthorUID,
			Comment:    picture.Comment,
		}
	}

	res = PictureListRes{
		Count: count,
		List:  list,
	}
	return
}

// 小学生才做选择题
func (*PictureContrl) ListLove(c *gin.Context) (res interface{}, e Error) {
	page := utils.Max(GetInt(c, "page"), 1)
	rows := utils.Min(GetInt(c, "rows"), 30)

	pictures := make([]db.PicLoveMysql, 0)
	count, err := mysql.FindList(&pictures, &mysql.Cond{
		Start: (page - 1) * rows,
		Limit: rows,
		Asc:   "id",
	})
	if err != nil {
		return nil, GenError(err)
	}

	list := make([]PictureItem, len(pictures))
	for k, picture := range pictures {
		list[k] = PictureItem{
			ID:         picture.ID,
			OriginName: picture.OriginName,
			Width:      100,
			Height:     genPicMiniHeight(picture.Width, picture.Height, 100),
			URL:        genPictureURL(picture.Name),
			MiniURL:    genPictureURL(env.GetMinPicName(picture.Name)),
			AuthName:   picture.AuthorName,
			AuthUID:    picture.AuthorUID,
			Comment:    picture.Comment,
		}
	}

	res = PictureListRes{
		Count: count,
		List:  list,
	}
	return
}

// 骑驴找马
func (*PictureContrl) ListConsider(c *gin.Context) (res interface{}, e Error) {
	page := utils.Max(GetInt(c, "page"), 1)
	rows := utils.Min(GetInt(c, "rows"), 30)

	pictures := make([]db.PicConsiderMysql, 0)
	count, err := mysql.FindList(&pictures, &mysql.Cond{
		Start: (page - 1) * rows,
		Limit: rows,
		Asc:   "id",
	})
	if err != nil {
		return nil, GenError(err)
	}

	list := make([]PictureItem, len(pictures))
	for k, picture := range pictures {
		list[k] = PictureItem{
			ID:         picture.ID,
			OriginName: picture.OriginName,
			Width:      100,
			Height:     genPicMiniHeight(picture.Width, picture.Height, 100),
			URL:        genPictureURL(picture.Name),
			MiniURL:    genPictureURL(env.GetMinPicName(picture.Name)),
			AuthName:   picture.AuthorName,
			AuthUID:    picture.AuthorUID,
			Comment:    picture.Comment,
		}
	}

	res = PictureListRes{
		Count: count,
		List:  list,
	}
	return
}

// 说出你的感觉
func (*PictureContrl) Feel(c *gin.Context) (res interface{}, e Error) {
	pictureType := GetInt(c, "type")
	feel := GetInt(c, "feel")
	id := GetInt64(c, "id")
	if feel <= 0 || feel == pictureType || id <= 0 {
		return nil, GenErrorMsg("参数错误")
	}

	var err error
	var picture map[string]interface{}
	session := mysql.NewSession()
	defer func() {
		if err != nil {
			session.Rollback()
		}
		session.Close()
	}()
	session.Begin()

	switch pictureType {
	case PictureTypeOriginal:
		pictureOriginal := &db.PicOriginalMysql{ID: id}
		err = session.Load(pictureOriginal)
		if err != nil {
			return nil, GenError(err)
		}
		pictureOriginal.ID = 0
		picture = map[string]interface{}{
			"ID":           pictureOriginal.ID,
			"Name":         pictureOriginal.Name,
			"OriginName":   pictureOriginal.OriginName,
			"Width":        pictureOriginal.Width,
			"Height":       pictureOriginal.Height,
			"Comment":      pictureOriginal.Comment,
			"AuthorName":   pictureOriginal.AuthorName,
			"AuthorUID":    pictureOriginal.AuthorUID,
			"UploadId":     pictureOriginal.UploadId,
			"UploadAtUnix": pictureOriginal.UploadAtUnix,
		}
		err = session.Del(db.PicOriginalMysql{ID: id})
	case PictureTypeLove:
		pictureLove := &db.PicLoveMysql{ID: id}
		err = session.Load(pictureLove)
		if err != nil {
			return nil, GenError(err)
		}
		pictureLove.ID = 0
		picture = map[string]interface{}{
			"ID":           pictureLove.ID,
			"Name":         pictureLove.Name,
			"OriginName":   pictureLove.OriginName,
			"Width":        pictureLove.Width,
			"Height":       pictureLove.Height,
			"Comment":      pictureLove.Comment,
			"AuthorName":   pictureLove.AuthorName,
			"AuthorUID":    pictureLove.AuthorUID,
			"UploadId":     pictureLove.UploadId,
			"UploadAtUnix": pictureLove.UploadAtUnix,
		}
		err = session.Del(db.PicLoveMysql{ID: id})
	case PictureTypeConsider:
		pictureConsider := &db.PicConsiderMysql{ID: id}
		err = session.Load(pictureConsider)
		if err != nil {
			return nil, GenError(err)
		}
		pictureConsider.ID = 0
		picture = map[string]interface{}{
			"ID":           pictureConsider.ID,
			"Name":         pictureConsider.Name,
			"OriginName":   pictureConsider.OriginName,
			"Width":        pictureConsider.Width,
			"Height":       pictureConsider.Height,
			"Comment":      pictureConsider.Comment,
			"AuthorName":   pictureConsider.AuthorName,
			"AuthorUID":    pictureConsider.AuthorUID,
			"UploadId":     pictureConsider.UploadId,
			"UploadAtUnix": pictureConsider.UploadAtUnix,
		}

		err = session.Del(db.PicConsiderMysql{ID: id})
	}
	if err != nil {
		return nil, GenError(err)
	}

	switch feel {
	case PictureTypeLove:
		love := db.PicLoveMysql{
			ID:           picture["ID"].(int64),
			Name:         picture["Name"].(string),
			OriginName:   picture["OriginName"].(string),
			Width:        picture["Width"].(int),
			Height:       picture["Height"].(int),
			Comment:      picture["Comment"].(string),
			AuthorName:   picture["AuthorName"].(string),
			AuthorUID:    picture["AuthorUID"].(int64),
			UploadId:     picture["UploadId"].(int64),
			UploadAtUnix: picture["UploadAtUnix"].(int64),
		}
		err = session.Create(&love)
	case PictureTypeConsider:
		consider := db.PicConsiderMysql{
			ID:           picture["ID"].(int64),
			Name:         picture["Name"].(string),
			OriginName:   picture["OriginName"].(string),
			Width:        picture["Width"].(int),
			Height:       picture["Height"].(int),
			Comment:      picture["Comment"].(string),
			AuthorName:   picture["AuthorName"].(string),
			AuthorUID:    picture["AuthorUID"].(int64),
			UploadId:     picture["UploadId"].(int64),
			UploadAtUnix: picture["UploadAtUnix"].(int64),
		}
		err = session.Create(&consider)
	}
	if err != nil {
		return nil, GenError(err)
	}
	err = session.Commit()
	if err != nil {
		return nil, GenError(err)
	}
	res = "ok"
	return
}

// 删除图
func (*PictureContrl) Del(c *gin.Context) (res interface{}, e Error) {
	pictureType := GetInt(c, "type")
	id := GetInt64(c, "id")

	var err error
	switch pictureType {
	case PictureTypeOriginal:
		picture := &db.PicOriginalMysql{ID: id}
		err = mysql.Load(picture)
		if err != nil {
			return nil, GenError(err)
		}
		err = minio_client.Client.RemoveObject(db.PicBucket, picture.Name)
		err = minio_client.Client.RemoveObject(db.PicBucket, env.GetMinPicName(picture.Name))
		if err != nil {
			return nil, GenError(err)
		}
		err = mysql.Del(picture)

	case PictureTypeLove:
		picture := &db.PicLoveMysql{ID: id}
		err := mysql.Load(picture)
		if err != nil {
			return nil, GenError(err)
		}
		err = minio_client.Client.RemoveObject(db.PicBucket, picture.Name)
		err = minio_client.Client.RemoveObject(db.PicBucket, env.GetMinPicName(picture.Name))
		if err != nil {
			return nil, GenError(err)
		}
		err = mysql.Del(picture)

	case PictureTypeConsider:
		picture := &db.PicConsiderMysql{ID: id}
		err := mysql.Load(picture)
		if err != nil {
			return nil, GenError(err)
		}
		err = minio_client.Client.RemoveObject(db.PicBucket, picture.Name)
		err = minio_client.Client.RemoveObject(db.PicBucket, env.GetMinPicName(picture.Name))
		if err != nil {
			return nil, GenError(err)
		}
		err = mysql.Del(picture)
	}
	if err != nil {
		return nil, GenError(err)
	}

	res = "ok"
	return
}

// 删除图
func (*PictureContrl) DelMulti(c *gin.Context) (res interface{}, e Error) {
	pictureType := GetInt(c, "type")
	idsStr := GetString(c, "ids")

	ids := strings.Split(idsStr, "_")
	var err error
	for _, idStr := range ids {
		id := utils.ToInt64(idStr)
		switch pictureType {
		case PictureTypeOriginal:
			picture := &db.PicOriginalMysql{ID: id}
			err = mysql.Load(picture)
			if err != nil {
				return nil, GenError(err)
			}
			err = minio_client.Client.RemoveObject(db.PicBucket, picture.Name)
			if err != nil {
				utils.Error(err)
			}
			err = mysql.Del(picture)

		case PictureTypeLove:
			picture := &db.PicLoveMysql{ID: id}
			err := mysql.Load(picture)
			if err != nil {
				return nil, GenError(err)
			}
			err = minio_client.Client.RemoveObject(db.PicBucket, picture.Name)
			if err != nil {
				utils.Error(err)
			}
			err = mysql.Del(picture)

		case PictureTypeConsider:
			picture := &db.PicConsiderMysql{ID: id}
			err := mysql.Load(picture)
			if err != nil {
				return nil, GenError(err)
			}
			err = minio_client.Client.RemoveObject(db.PicBucket, picture.Name)
			if err != nil {
				utils.Error(err)
			}
			err = mysql.Del(picture)
		}
		if err != nil {
			return nil, GenError(err)
		}
	}

	res = "ok"
	return
}
